using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Resources;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Core.Mapping;
using Core.Graphics;
using WorldEditor.Properties;
using System.Collections;


namespace WorldEditor
{
    public enum TileTools
    {
        Pan,
        Pencil,
        PaintBucket,
        RectangleSelect,
        EllipseSelect,
        LassoSelect,
        MagicWand,
        Eraser,
        EyeDropper,
    }

    public partial class CanvasPanel : XNAPanel
    {
        /// <summary>Event For when the world coordinate the mouse is hovering over is changed</summary>
        public event EventHandler HoverCoordinateChanged;
        public event EventHandler PrimaryTileChanged;

        public Point CurrentCursor { get { return _CurrentCursor; } set { _CurrentCursor = value; } }

        public TileTools CurrentlyTool { get { return _CurrentTool; } }
        public bool DrawGrid { get { return _DrawGrid; } set { _DrawGrid = value; } }
        public ArrayList SelectedArea { get { return _SelectedArea; } }

        public TileSetTile PrimaryTile 
        { 
            get { return _PrimaryTile; } 
            set { 
                _PrimaryTile = value;
                tssbCurrentTile.Image = TileSetTileBitmaps.GetTileBitmap(value.SpriteID, TileSetTypes.Terrain);
            } 
        }
        public TileSetTile SecondaryTile { get { return _SecondaryTile; } set { _SecondaryTile = value; } }

        public Texture2D CursorTile { get { return _CursorTile; } set { _CursorTile = value; } }
        public Texture2D GridTile { get { return _GridTile; } set { _GridTile = value; } }

        public ToolStrip CanvasToolStrip { get { return tsMapEditTools; } set { tsMapEditTools = value; } }

        public Point CurrentLocation { get { return _CurrentLocation; } set { _CurrentLocation = value; } }
        public Point CurrentTopLeftLocation { get { return _CurrentTopLeftLocation; } set { _CurrentTopLeftLocation = value; } }
        
        public virtual Rectangle DrawArea
        {
            get { return _DrawArea; }
            set
            {
                _DrawArea = value;
                _CurrentLocation.X = value.X;
                _CurrentLocation.Y = value.Y;
                _CurrentTopLeftLocation = _CurrentLocation;
            }
        }

        protected Rectangle _DrawArea;

        protected Point _CurrentLocation = new Point();
        protected Point _CurrentTopLeftLocation = new Point();

        protected Point _CurrentCursor = new Point();
        protected Point _CurrentDrawCursor = new Point();

        protected TileTools _CurrentTool;
        protected bool _DrawGrid;
        protected bool _MouseDown;
        protected Point _MouseStartWorldLocation;
        protected Point _MouseStartScreenLocation;

        protected ArrayList _SelectedArea;
        protected ArrayList _TempSelectedArea;

        protected TileSetTile _PrimaryTile;
        protected TileSetTile _SecondaryTile;

        protected Texture2D _CursorTile;
        protected Texture2D _GridTile;

        protected bool _Shift = false;

        #region Toolbar
        private void DeselectTools()
        {
            foreach (ToolStripItem tsi in tsMapEditTools.Items)
            {
                if (tsi is ToolStripButton)
                {
                    ((ToolStripButton)tsi).Checked = false;
                }
            }
        }

        #region Pan
        private void tsbPan_Click(object sender, EventArgs e)
        {
            PickPan();
        }

        private void PickPan()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbPan.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.Pan);
        }
        #endregion

        #region Clear Selection
        private void tsbClearSelection_Click(object sender, EventArgs e)
        {
            this.ClearSelection();
        }
        #endregion

        #region Rectangle Select
        private void tsbSelectRect_Click(object sender, EventArgs e)
        {
            PickRectangleSelect();
        }

        private void PickRectangleSelect()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbSelectRect.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.RectangleSelect);
        }
        #endregion

        #region Ellipse Select
        //Ellipse Select is not currently enabled
        private void tsbEllipseSelect_Click(object sender, EventArgs e)
        {
            PickEllipseSelect();
        }

        private void PickEllipseSelect()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //check icon
            tsbEllipseSelect.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.EllipseSelect);
        }
        #endregion

        #region Lasso Select
        //Lasso Select is currently not in use
        private void tsbLassoSelect_Click(object sender, EventArgs e)
        {
            PickLassoSelect();
        }

        private void PickLassoSelect()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //select lasso icon
            tsbLassoSelect.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.LassoSelect);
        }
        #endregion

        #region Magic Wand
        private void tsbMagicWand_Click(object sender, EventArgs e)
        {
            PickMagicWand();
        }

        private void PickMagicWand()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbMagicWand.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.MagicWand);
        }
        #endregion

        #region Pencil
        private void tsbPencil_Click(object sender, EventArgs e)
        {
            PickPencil();
        }

        private void PickPencil()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbPencil.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.Pencil);
        }
        #endregion

        #region Fill
        private void tsbFill_Click(object sender, EventArgs e)
        {
            PickFill();
        }

        private void PickFill()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbFill.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.PaintBucket);
        }
        #endregion

        #region Eraser
        private void tsbErase_Click(object sender, EventArgs e)
        {
            PickEraser();
        }

        private void PickEraser()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbErase.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.Eraser);
        }
        #endregion

        #region Tile Picker
        private void tsbEyeDropper_Click(object sender, EventArgs e)
        {
            PickTilePicker();
        }

        private void PickTilePicker()
        {
            //Deselect currelty checked tool
            DeselectTools();
            //Check new tool
            tsbEyeDropper.Checked = true;
            //Set as the active tool for the map editor
            this.SetActiveTool(TileTools.EyeDropper);
        }
        #endregion

        private void tsslSwapTiles_Click(object sender, EventArgs e)
        {
            TileSetTile pt = this.PrimaryTile;
            this.PrimaryTile = this.SecondaryTile;
            this.SecondaryTile = pt;

            tssbCurrentTile.Image = TileSetTileBitmaps.GetTileBitmap(this.PrimaryTile.SpriteID, TileSetTypes.Terrain);
            tssbCurrentSecondaryTile.Image = TileSetTileBitmaps.GetTileBitmap(this.SecondaryTile.SpriteID, TileSetTypes.Terrain);
        }

        private void ScaleChangeClick(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem tsi in tsdScale.DropDownItems)
            {
                tsi.Checked = false;
            }

            ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
            tsmi.Checked = true;
            tsdScale.Text = tsmi.Text;

            double scale = Convert.ToDouble(tsmi.Text.Replace("%", "")) / 100.00;

            double newHeight = Tile.TileHeight * scale;
            double newWidth = Tile.TileWidth * scale;

            Tile.ScaledTileHeight = Convert.ToInt32(newHeight);
            Tile.ScaledTileWidth = Convert.ToInt32(newWidth);

            this.UpdateDrawingArea();
        }
    #endregion

        public CanvasPanel()
        {
            InitializeComponent();
            CreateCursorTile(Color.Blue);                         
            //Create the Grid Tile, for drawing our Grid if we have one.
            CreateGridTile(Color.Black);
            //Set Defaults
            _PrimaryTile = TileSetTile.BlankTile;
            _SecondaryTile = TileSetTile.BlankTile;
            SetActiveTool(TileTools.Pan);
        }

        protected void CreateGridTile(Color GridColor)
        {
            Vector4 v4 = GridColor.ToVector4();
            v4.W = 0.2f;
            Color semi = new Color(v4);
            //Create Grid Texture
            _GridTile = new Texture2D(GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color);
            Color[] colors = new Color[1];
            colors[0] = semi;

            _GridTile.SetData<Color>(colors);
        }

        protected void CreateCursorTile(Color GridColor)
        {
            Vector4 v4 = GridColor.ToVector4();
            v4.W = 0.2f;
            Color semi = new Color(v4);
            //Create Grid Texture
            _CursorTile = new Texture2D(GraphicsDevice, 32, 32, 1, TextureUsage.None, SurfaceFormat.Color);
            Color[] colors = new Color[32*32];

            for (int i = 0; i < 32 * 32; i++)
            {
                colors[i] = semi;
            }

            _CursorTile.SetData<Color>(colors);
        }

        protected override void MouseMove(MouseEventArgs mouseargs)
        {
            _CurrentCursor = new Point(mouseargs.X, mouseargs.Y);

            _CurrentDrawCursor = new Point(mouseargs.X / Tile.ScaledTileWidth, mouseargs.Y / Tile.ScaledTileHeight);

            //HoveringCoordinateChanged();

            base.MouseMove(mouseargs);

            if (_MouseDown)
                ExecuteTool();
        }

        protected new virtual void MouseDown(object sender, MouseEventArgs e)
        {
            _MouseDown = true;
            _MouseStartScreenLocation = _CurrentDrawCursor;
            ExecuteTool();
        }

        protected new virtual void MouseUp(object sender, MouseEventArgs e)
        {
            _MouseDown = false;

            if (_TempSelectedArea != null)
            {
                if (!_Shift)
                {
                    _SelectedArea = (ArrayList)_TempSelectedArea.Clone();
                    _TempSelectedArea = null;
                }
                else
                {
                    foreach (Point pt in _TempSelectedArea)
                    {
                        if (!_SelectedArea.Contains(pt))
                            _SelectedArea.Add(pt);
                    }

                    _TempSelectedArea = null;
                }
            }
        }

        protected override void KeyPressDown(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.M:
                    PickPan(); break;
                case Keys.P:
                    PickPencil(); break;
                case Keys.F:
                    PickFill(); break;
                case Keys.R:
                    PickRectangleSelect(); break;
                case Keys.W:
                    PickMagicWand(); break;
                case Keys.ShiftKey:
                    _Shift = true; break;
            }

            base.KeyPressDown(e);
        }

        protected override void KeyPressUp(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.ShiftKey)
                _Shift = false;

            base.KeyPressUp(e);
        }

        #region Tools
        public void SetActiveTool(TileTools tool)
        {
            _CurrentTool = tool;

            switch (_CurrentTool)
            {
                case TileTools.Eraser:
                    Cursor = new Cursor(Resources.tool_eraser.GetHicon());
                    break;
                case TileTools.EyeDropper:
                    Cursor = new Cursor(Resources.tool_color_picker.GetHicon());
                    break;
                case TileTools.LassoSelect:
                    Cursor = new Cursor(Resources.tool_free_select.GetHicon());
                    break;
                case TileTools.MagicWand:
                    Cursor = new Cursor(Resources.tool_fuzzy_select.GetHicon());
                    break;
                case TileTools.PaintBucket:
                    Cursor = new Cursor(Resources.tool_bucket_fill.GetHicon());
                    break;
                case TileTools.Pan:
                    Cursor = new Cursor(Resources.tool_move.GetHicon());
                    break;
                case TileTools.Pencil:
                    Cursor = new Cursor(Resources.tool_pencil.GetHicon());
                    break;
                case TileTools.RectangleSelect:
                    Cursor = new Cursor(Resources.tool_rect_select.GetHicon());
                    break;
                case TileTools.EllipseSelect:
                    Cursor = new Cursor(Resources.tool_ellipse_select.GetHicon());
                    break;
                default:
                    Cursor = Cursors.Default;
                    break;
            }
        }

        protected virtual void ExecuteTool()
        {
            switch (_CurrentTool)
            {
                case TileTools.Pan:
                    Pan();
                    break;
                case TileTools.Pencil:
                    Pencil();
                    break;
                case TileTools.EyeDropper:
                    EyeDropper();
                    break;
                case TileTools.Eraser:
                    Eraser();
                    break;
                case TileTools.PaintBucket:
                    PaintBucket();
                    break;
                case TileTools.RectangleSelect:
                    RectangleSelect();
                    break;
                case TileTools.EllipseSelect:
                    EllipseSelect();
                    break;
                case TileTools.MagicWand:
                    MagicWand();
                    break;
            }
        }

        protected virtual void Pan() { }
        protected virtual void Pencil() { }
        protected virtual void EyeDropper() { }
        protected virtual void Eraser() { }
        protected virtual void PaintBucket() { }
        protected virtual void MagicWand() { }
        protected virtual void RectangleSelect() { }
        protected virtual void EllipseSelect() { }

        #endregion

        public virtual void ClearSelection()
        {
            _TempSelectedArea = null;
            _SelectedArea = null;
        }

        protected void HoveringCoordinateChanged(Point CurrentCursor)
        {
            if (HoverCoordinateChanged != null)
                HoverCoordinateChanged.Invoke(CurrentCursor, null);
        }

        protected void OnPrimaryTileChanged()
        {
            if (PrimaryTileChanged != null)
                PrimaryTileChanged.Invoke(_PrimaryTile, EventArgs.Empty);
        }

        public void UpdateDrawingArea()
        {
            _DrawArea = new Rectangle(_DrawArea.X, _DrawArea.Y, (this.Width / Tile.ScaledTileWidth) + 1, (this.Height / Tile.ScaledTileHeight) + 1);
        }

        protected override void Draw()
        {
            if (_DrawGrid) DrawScreenGrid();

            base.Draw();
        }
        
        protected void DrawScreenGrid()
        {            
            SpriteBatch.Begin(SpriteBlendMode.AlphaBlend);

            for (int y = 0; y < (pnlEditor.Height / Tile.ScaledTileHeight) + 1; y++)
            {
                SpriteBatch.Draw(_GridTile, new Rectangle(0, y * Tile.ScaledTileHeight, pnlEditor.Width, 2), Color.White);
            }

            for (int x = 0; x < (pnlEditor.Width / Tile.ScaledTileWidth) + 1; x++)
            {
                SpriteBatch.Draw(_GridTile, new Rectangle(x * Tile.ScaledTileWidth, 0, 2, pnlEditor.Height), Color.White);
            }

            SpriteBatch.End();
        }

        private void tsbShowGrid_Click(object sender, EventArgs e)
        {
            //on click, swap show grid status
            DrawGrid = !tsbShowGrid.Checked;

            //set checked status of tool strip button
            tsbShowGrid.Checked = DrawGrid;
        }
    }
}
